from json import dumps

from django import forms
from django.contrib.auth.forms import AuthenticationForm, UsernameField
from phonenumber_field.formfields import RegionalPhoneNumberWidget

from main.models import Client, Request, RequestAttachment


class GeneratedForm(forms.Form):
    def __init__(self, structure: list[dict], *args, **kwargs):
        """
        :param structure: JSON string with form structure
        """
        super().__init__(*args, **kwargs)

        self.label_suffix = ""

        if not isinstance(self.initial, dict):
            raise ValueError("Initial data must be a dict!")

        self.structure = structure
        self.fields = self.generate_fields()

    def get_json(self) -> str:
        return dumps(self.cleaned_data)

    def get_name_val(self):
        name_val = []

        for field in self.structure:
            if field["type"] == "group" or field["name"] not in self.initial:
                continue
            val = self.initial[field["name"]]
            if isinstance(val, bool):
                val = "Да" if val else "Нет"
            elif field["type"] == "select":
                val = dict(field["choices"]).get(val)
            name_val.append((field["label"], val))

        return name_val

    def generate_fields(self):
        """
        Функция генерирует поля по группам из JSON структуры

        return: fields, grouped Поля и сгруппированные поля
        """

        fields = {}
        group = None
        for field in self.structure:
            if field["type"] == "group":
                group = field["name"]
            elif field["type"] == "text":
                dj_field = forms.CharField(
                    label=field["label"], required=field["required"]
                )
                dj_field.group = group
                fields[field["name"]] = dj_field
            elif field["type"] == "integer":
                dj_field = forms.IntegerField(
                    label=field["label"], required=field["required"]
                )
                dj_field.group = group
                fields[field["name"]] = dj_field
            elif field["type"] == "text_area":
                dj_field = forms.CharField(
                    label=field["label"],
                    widget=forms.Textarea(attrs={"rows": "4"}),
                    required=field["required"],
                )
                dj_field.group = group
                fields[field["name"]] = dj_field
            elif field["type"] == "select":
                dj_field = forms.ChoiceField(
                    label=field["label"],
                    choices=field["choices"],
                    required=field["required"],
                )
                dj_field.group = group
                fields[field["name"]] = dj_field
            elif field["type"] == "check":
                dj_field = forms.BooleanField(
                    label=field["label"], required=field["required"]
                )
                dj_field.group = group
                fields[field["name"]] = dj_field

        return fields


class UserLoginForm(AuthenticationForm):
    error_css_class = "is-invalid"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    username = UsernameField(
        label="Логин",
        widget=forms.TextInput(attrs={"class": "peer form-control"}),
    )
    password = forms.CharField(
        label="Пароль",
        widget=forms.PasswordInput(attrs={"class": "peer form-control"}),
    )


class ClientForm(forms.ModelForm):
    class Meta:
        model = Client
        fields = ("first_name", "last_name", "phone_number", "email", "note")

        widgets = {
            "phone_number": RegionalPhoneNumberWidget(
                attrs={
                    "pattern": r"\+7\s[\(]\d{3}[\)]\s\d{3}\s\d{2}\d{2}",
                }
            ),
            "email": forms.EmailInput(),
            "note": forms.Textarea(attrs={"rows": "4"}),
        }


class RequestForm(forms.ModelForm):
    client = forms.ModelChoiceField(
        Client.objects.none(), label="Связанный Клиент", required=False
    )

    class Meta:
        model = Request
        fields = (
            "first_name",
            "phone_number",
            "client",
            "note",
            "status",
            "archived",
        )

        widgets = {
            "phone_number": RegionalPhoneNumberWidget(
                attrs={"pattern": r"\+7\s[\(]\d{3}[\)]\s\d{3}\s\d{2}\d{2}"}
            ),
            "note": forms.Textarea(attrs={"rows": "4"}),
        }


class MeasureSheetFrom(forms.Form):
    WIDGETS = {
        "text": forms.TextInput(),
        "text_area": forms.Textarea(attrs={"rows": "4"}),
        "check": forms.CheckboxInput(),
        "select": forms.Select(),
        "integer": forms.NumberInput(),
    }

    final_measure = forms.BooleanField(
        label="Финальные размеры", required=False, widget=WIDGETS["check"]
    )
    final_measure.group = "Основное"
    need_socket_diagram = forms.BooleanField(
        label="Требуется схема розеток", required=False, widget=WIDGETS["check"]
    )
    need_socket_diagram.group = "Основное"

    # Параметры помещения
    main_size_wall_a = forms.IntegerField(
        label="Стена A (мм)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_a.group = "Параметры помещения (основные)"
    main_size_wall_b = forms.IntegerField(
        label="Стена B (мм)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_b.group = "Параметры помещения (основные)"
    main_size_wall_c = forms.IntegerField(
        label="Стена C (мм)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_c.group = "Параметры помещения (основные)"
    main_size_wall_ab = forms.IntegerField(
        label="Угол AB (гр)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_ab.group = "Параметры помещения (основные)"
    main_size_wall_bc = forms.IntegerField(
        label="Угол BC (гр)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_bc.group = "Параметры помещения (основные)"
    main_size_wall_h = forms.IntegerField(
        label="Высота h (мм)", required=False, widget=WIDGETS["integer"]
    )
    main_size_wall_h.group = "Параметры помещения (основные)"

    additional_size_wall_a1 = forms.IntegerField(
        label="Стена A1 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_a1.group = "Параметры помещения (дополнительные)"
    additional_size_wall_a2 = forms.IntegerField(
        label="Стена A2 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_a2.group = "Параметры помещения (дополнительные)"
    additional_size_wall_a3 = forms.IntegerField(
        label="Стена A3 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_a3.group = "Параметры помещения (дополнительные)"

    additional_size_wall_b1 = forms.IntegerField(
        label="Стена B1 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_b1.group = "Параметры помещения (дополнительные)"
    additional_size_wall_b2 = forms.IntegerField(
        label="Стена B2 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_b2.group = "Параметры помещения (дополнительные)"
    additional_size_wall_b3 = forms.IntegerField(
        label="Стена B3 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_b3.group = "Параметры помещения (дополнительные)"

    additional_size_wall_c1 = forms.IntegerField(
        label="Стена C1 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_c1.group = "Параметры помещения (дополнительные)"
    additional_size_wall_c2 = forms.IntegerField(
        label="Стена C2 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_c2.group = "Параметры помещения (дополнительные)"
    additional_size_wall_c3 = forms.IntegerField(
        label="Стена C3 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_c3.group = "Параметры помещения (дополнительные)"

    additional_size_wall_h1 = forms.IntegerField(
        label="Высота h1 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_h1.group = "Параметры помещения (дополнительные)"
    additional_size_wall_h2 = forms.IntegerField(
        label="Высота h2 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_h2.group = "Параметры помещения (дополнительные)"
    additional_size_wall_h3 = forms.IntegerField(
        label="Высота h3 (мм)", required=False, widget=WIDGETS["integer"]
    )
    additional_size_wall_h3.group = "Параметры помещения (дополнительные)"

    # Материалы
    material_wall_a = forms.CharField(
        label="Стена A", required=False, widget=WIDGETS["text"]
    )
    material_wall_a.group = "Материалы"
    material_wall_b = forms.CharField(
        label="Стена B", required=False, widget=WIDGETS["text"]
    )
    material_wall_b.group = "Материалы"
    material_wall_c = forms.CharField(
        label="Стена C", required=False, widget=WIDGETS["text"]
    )
    material_wall_c.group = "Материалы"
    material_ceiling = forms.CharField(
        label="Потолок", required=False, widget=WIDGETS["text"]
    )
    material_ceiling.group = "Материалы"
    material_floor = forms.CharField(
        label="Пол", required=False, widget=WIDGETS["text"]
    )
    material_floor.group = "Материалы"
    material_apron = forms.CharField(
        label="Фартук", required=False, widget=WIDGETS["text"]
    )
    material_apron.group = "Материалы"

    # Ручки
    HANDLE_CHOICES = (
        ("N", "Без ручек"),
        ("PFL", "Профиль F лайн"),
        ("PML", "Профиль M лайн"),
        ("IN", "Интегрированная ручка"),
        ("HANDLDRIL", "C ручкой, со сверлением"),
        ("LED", "C LED подсветкой"),
    )
    lower_modules = forms.ChoiceField(
        label="Нижние модули",
        choices=HANDLE_CHOICES,
        required=False,
        widget=WIDGETS["select"],
    )
    lower_modules.group = "Ручки"
    upper_modules = forms.ChoiceField(
        label="Верхние модули",
        choices=HANDLE_CHOICES,
        required=False,
        widget=WIDGETS["select"],
    )
    upper_modules.group = "Ручки"

    # Техника
    tech_boiler_built_in = forms.BooleanField(
        label="Котел отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_boiler_built_in.group = "Техника"
    tech_boiler_desc = forms.CharField(
        label="Котел", required=False, widget=WIDGETS["text"]
    )
    tech_boiler_desc.group = "Техника"

    tech_stove_built_in = forms.BooleanField(
        label="Плита отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_stove_built_in.group = "Техника"
    tech_stove_desc = forms.CharField(
        label="Плита", required=False, widget=WIDGETS["text"]
    )
    tech_stove_desc.group = "Техника"
    # tech_cooking_stove_built_in = forms.BooleanField(label='Вароч отдельно')

    tech_cooking_stove_desc = forms.CharField(
        label="Варочная", required=False, widget=WIDGETS["text"]
    )
    tech_cooking_stove_desc.group = "Техника"

    tech_oven_desc = forms.CharField(
        label="Духовой шкаф", required=False, widget=WIDGETS["text"]
    )
    tech_oven_desc.group = "Техника"

    tech_range_hood_built_in = forms.BooleanField(
        label="Вытяжка отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_range_hood_built_in.group = "Техника"
    tech_range_hood_desc = forms.CharField(
        label="Вытяжка", required=False, widget=WIDGETS["text"]
    )
    tech_range_hood_desc.group = "Техника"

    tech_dishwasher_built_in = forms.BooleanField(
        label="ПММ отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_dishwasher_built_in.group = "Техника"
    tech_dishwasher_desc = forms.CharField(
        label="ПММ", required=False, widget=WIDGETS["text"]
    )
    tech_dishwasher_desc.group = "Техника"

    tech_washing_built_in = forms.BooleanField(
        label="Стиральная отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_washing_built_in.group = "Техника"
    tech_washing_desc = forms.CharField(
        label="Стиральная", required=False, widget=WIDGETS["text"]
    )
    tech_washing_desc.group = "Техника"

    tech_microwave_built_in = forms.BooleanField(
        label="Мирковолновка отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_microwave_built_in.group = "Техника"
    tech_microwave_desc = forms.CharField(
        label="Мирковолновка", required=False, widget=WIDGETS["text"]
    )
    tech_microwave_desc.group = "Техника"

    tech_fridge_built_in = forms.BooleanField(
        label="Холодильник отдельно", required=False, widget=WIDGETS["check"]
    )
    tech_fridge_built_in.group = "Техника"
    tech_fridge_desc = forms.CharField(
        label="Холодильник", required=False, widget=WIDGETS["text"]
    )
    tech_fridge_desc.group = "Техника"

    tech_other_desc = forms.CharField(
        label="Другое", required=False, widget=WIDGETS["text_area"]
    )
    tech_other_desc.group = "Техника"

    # Мойка
    sink_size = forms.IntegerField(
        label="Размер (см)", required=False, widget=WIDGETS["integer"]
    )
    sink_size.group = "Мойка"
    SINK_MONTAGE_CHOICES = (
        ("MR", "Врезной"),
        ("UND", "Подстольный"),
        ("IN", "Интегрированный"),
    )
    sink_montage = forms.ChoiceField(
        label="Монтаж",
        choices=SINK_MONTAGE_CHOICES,
        required=False,
        widget=WIDGETS["select"],
    )
    sink_montage.group = "Мойка"

    # Комментарий замерщика
    comment = forms.CharField(
        label="Примечания замерщика",
        required=False,
        widget=WIDGETS["text_area"],
    )
    comment.group = "Дополнительно"


class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True


class RequestAttachsForm(forms.ModelForm):
    class Meta:
        model = RequestAttachment
        fields = ("file",)

        widgets = {
            "file": MultipleFileInput(
                attrs={"class": "form-control-file", "multiple": True}
            ),
        }
